﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace BarStructures
{
    public partial class DrawBoard : UserControl, IDrawBoard
    {
        private IDrawableModel model = null;

        private Bitmap bufferBitmap = null;

        private int horizontalBorder = 25;

        private int verticalBorder = 25;

        Transformations tr = null;

        public DrawBoard()
        {
            InitializeComponent();
        }

        public IDrawableModel DrawableModel
        {
            get { return model; }
            set
            {
                this.model = value;
                this.tr = ScaleParams(this.bufferBitmap, this.horizontalBorder, this.verticalBorder);
                this.Refresh();
            }
        }

        public Bitmap GetPicture()
        {
            int bound = 18;
            BoundingBox bbox = model.GetModelEnvelope();
            PointF min = GetWindowCoordinates(bbox.MinX, bbox.MinY);
            PointF max = GetWindowCoordinates(bbox.MaxX, bbox.MaxY);

            Bitmap result = new Bitmap((int)(max.X - min.X) + 2 * bound + 5, (int)(min.Y - max.Y) + 2 * bound);
            RectangleF destRect = Graphics.FromImage(result).VisibleClipBounds;
            
            Graphics.FromImage(result).DrawImage(bufferBitmap, destRect,
                new RectangleF((int)(min.X - bound),
                               (int)(max.Y - bound),
                               (int)(max.X - min.X + 2 * bound + 5),
                               (int)(min.Y - max.Y + 2 * bound)), 
                GraphicsUnit.Pixel);
            return result;
        }

        private Transformations ScaleParams(Bitmap bmp, int hBorder, int vBorder)
        {
            if (model != null)
            {

                //описывающий прямоугольник для модели
                BoundingBox modelEnvelope = model.GetModelEnvelope();

                //рамка
                Rectangle clipRect = new Rectangle(hBorder, vBorder,
                    bmp.Width - 2 * hBorder, bmp.Height - 2 * vBorder);

                Transformations tr = new Transformations();

                //масштабирование
                double scale;
                if (clipRect.Height / modelEnvelope.Height < clipRect.Width / modelEnvelope.Width)
                    scale = clipRect.Height / modelEnvelope.Height;
                else
                    scale = clipRect.Width / modelEnvelope.Width;

                //перенос начала системы координат (реальные единицы измерения)
                double dx = modelEnvelope.MinX - (clipRect.Width / scale - modelEnvelope.Width) / 2;
                double dy = clipRect.Height / scale + modelEnvelope.MinY - (clipRect.Height / scale - modelEnvelope.Height) / 2;

                tr.ScaleX = scale;
                tr.ScaleY = -scale;
                tr.Dx = dx - horizontalBorder / scale;
                tr.Dy = dy + verticalBorder / scale;

                return tr;
            }
            return null;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (model != null)
            {
                //буфер для рисования
                if (bufferBitmap == null)
                    CreateBufferBitmap();
                //Graphics graphics = Graphics.FromImage(bufferBitmap);
                g.Clear(Color.White);

                if (this.tr == null)
                    this.tr = ScaleParams(this.bufferBitmap, this.horizontalBorder, this.verticalBorder);

                model.Draw(this);

                Graphics.FromHwnd(this.Handle).DrawImageUnscaled(bufferBitmap, 0, 0);
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (this.Width != 0 && this.Height != 0)
            {
                CreateBufferBitmap();
                this.tr = ScaleParams(this.bufferBitmap, this.horizontalBorder, this.verticalBorder);
                Refresh();
            }
        }

        private void CreateBufferBitmap()
        {
            bufferBitmap = new Bitmap(this.Width, this.Height);
            g = Graphics.FromImage(bufferBitmap);
        }

        #region IDrawBoard Members

        public PointF GetWindowCoordinates(double rX, double rY)
        {
            return new PointF((float)((rX - tr.Dx) * tr.ScaleX), (float)((rY - tr.Dy) * tr.ScaleY));
        }

        Graphics g = null;
        public Graphics GetGraphics()
        {
            //return Graphics.FromImage(bufferBitmap);
            return g;
        }

        #endregion
    }
}
